import {AttackAudio, TankCrackAudio, TankImage} from "./const.ts";
import {EventModel, GameModel, isMap, mainCtx, MoveableModel} from "./core.ts";
import {Bullet} from "./Bullet.ts";
import {GameMap} from "./GameMap.ts";
import {game} from "./Game.ts";

const keys: Set<string> = new Set()
const tankImgPos = {
    p1: {
        right: [[96, 0, 15, 15], [112, 0, 15, 15]],
        left: [[33, 0, 15, 15], [49, 0, 15, 15]],
        top: [[0, 1, 15, 15], [16, 1, 15, 15]],
        bottom: [[64, 0, 15, 15], [80, 0, 15, 15]]
    },
    p2: {
        right: [[224, 0, 15, 15], [240, 0, 15, 15]],
        left: [[161, 0, 15, 15], [177, 0, 15, 15]],
        top: [[128, 1, 15, 15], [144, 1, 15, 15]],
        bottom: [[192, 0, 15, 15], [208, 0, 15, 15]]
    },
} as { [key: string]: { [key: string]: number[][] } }

export class Tank extends MoveableModel {
    type = 'p1'
    camp =1
    _frame = 0
    bullets = 0

    constructor(x: number, y: number) {
        super(x, y, 32, 32, mainCtx);
    }

    fire() {
        if (this.bullets == 0){
            this.bullets ++
            new Bullet(this.x, this.y, this.direction, this).reg()
        }
    }

    render(): void {
        if (this.moving) {
            this._frame++
            if (this._frame >= 12) {
                this._frame = 0
            }
        }
        let imgPos = tankImgPos[this.type][this.direction][this._frame < 6 ? 0 : 1]
        this.ctx.drawImage(TankImage, imgPos[0], imgPos[1], imgPos[2], imgPos[3], this.x - 16, this.y - 16, this.width, this.height)
    }

    turn(direction: string) {
        if (this.direction != direction){
            this.direction = direction
            this.x = Math.round(this.x / 16) * 16
            this.y = Math.round(this.y / 16) * 16
        }
    }

    update(time: number): void {
        super.update(time)
    }

    compact(_: GameModel|GameMap): void {

    }
    destroy() {
        super.destroy();
        if (!TankCrackAudio.paused) {
            TankCrackAudio.currentTime = 0; // 重置音频播放时间
        }
        TankCrackAudio.play();
    }

}
export function isTank(model: any): model is Tank {
    return model instanceof Tank
}

export class Player extends Tank implements EventModel {
    type = 'p1'

    constructor(x: number, y: number) {
        super(x, y);
    }

    onkeydown(e: KeyboardEvent): void {
        const keyMap = {
            d: {alert: "right", direction: "right"},
            a: {alert: "left", direction: "left"},
            w: {alert: "top", direction: "top"},
            s: {alert: "bottom", direction: "bottom"},
            j: {action: "fire"}
        } as { [key: string]: any };
        const action = keyMap[e.key];
        if (action) {
            if (action.alert) {
                keys.add(e.key)
                this.turn(action.direction)
                this.moving = true;
            } else if (action.action === "fire") {
                this.fire()
            }
        }
    }

    fire() {
        if (this.bullets <= 0){
            this.bullets ++
            new Bullet(this.x, this.y, this.direction, this).reg()
            if (!AttackAudio.paused) {
                AttackAudio.currentTime = 0; // 重置音频播放时间
            }
            AttackAudio.play();
        }
    }

    onkeyup(e: KeyboardEvent): void {

        const keymap = ['d', 'a', 'w', 's']
        if (keymap.includes(e.key)) {
            keys.delete(e.key)
            if (keys.size == 0) {
                this.moving = false
            }
        }
    }
    destroy() {
        super.destroy();
        game.playerDie()
    }
}

export class Enemy extends Tank {
    type = 'p2'
    moving = true
    camp = 2

    constructor(x: number, y: number) {
        super(x, y);
    }

    update(time: number) {
        super.update(time);
        this.ai(time)
    }

    compact(model: GameModel|GameMap) {
        super.compact(model);
        if (isMap(model)){
            let direction = ["top", "bottom", "left", "right"][Math.floor(Math.random() * 4)]
            this.turn(direction)
        }

    }

    ai(_: number) {
        let t = Math.floor(Math.random() * 128)
        if (t % 128 == 0) {
            let direction = ["top", "bottom", "left", "right"][Math.floor(Math.random() * 4)]
            if (this.direction != direction){
                this.turn(direction)
            }
        }
        t = Math.floor(Math.random() * 128)
        if (t % 4 == 0) {
            this.fire()
        }
    }
    destroy() {
        super.destroy();
        game.enemyDie()
    }
}